#include "iic.h"
#include "Include.h"

const uint16 code EE_TH[2][2] =          //IIC timer divider threshold
{0x0001, 0x0000,
 0x0020, 0x0007,};



uint8 IIC_Start_Ex(void);                  //transmit start bit
uint8 IIC_ReStart_Ex(void);                   //transmit restart bit
uint8 IIC_Stop_Ex(void);                   //transmit stop bit
uint8 IIC_Send_Data_Ex(uint8 txd);            //transmit 8-bit data byte
uint8 IIC_Read_Data_Ex(uint8 *rd_val, uint8 ack);   //receive 8-bit data byte

/**
* @brief  IIC initialization.
* @param  mcu_frq: The current MCUCLK frequency.
*   This parameter can be one of the following values:
*       MCU_FRQ_800K: 0x00 MCUCLK frequency = 800kHz
*       MCU_FRQ_13M: 0x01 MCUCLK frequency = 13M
*         baud: The IIC baudrate to be configured.
*   This parameter can be one of the following values:
*       IIC_BAUD_100K: baudrate 100Kbps
*       IIC_BAUD_400K: baudrate 400Kbps
* @retval 0: successful
*         1: failed
*/
uint8 IIC_Init(uint8 mcu_frq, uint8 baud)
{
    IIC_GPIO_Init();                    //Configure I/O ports
    IIC_Set_Period(EE_TH[mcu_frq][baud]);   //Configure timer divider threshold
    
    if (IIC_Stop() == 1)                //transmit stop bit failed
        return 1;
    if (IIC_Wait_Busy() == 1)           //check busy state
        return 1;
    
    return 0;
}

/**
* @brief  read one byte
* @param  rd_addr: EEPROM memory address
*         rd_buff: Data buffer to restore read data.
* @retval 0: successful
*         1：failed
*         2：EEPROM type err
*/
uint8 IIC_RD_B(uint32 rd_addr, uint8 *rd_buff)
{
    return IIC_RD_P(rd_addr, rd_buff, 1);
}

/**
* @brief  read page
* @param  rd_addr: EEPROM memory address
*         rd_buff: Data buffer to restore read data.
*         rd_len: The number of bytes to read from EEPROM.
* @retval 0: successful
*         1：failed
*         2：EEPROM type err
*/
uint8 IIC_RD_P(uint32 rd_addr, uint8 *rd_buff, uint32 rd_len)
{
  return 0;
}

/**
* @brief  write one byte
* @param  wr_addr: EEPROM memory address
*         wr_buff: Data buffer to restore write data.
* @retval 0: successful
*         1：failed
*         2：EEPROM type err
*/
uint8 IIC_WR_B(uint32 wr_addr, uint8 wr_buff)
{
    return IIC_WR_P(wr_addr, &wr_buff, 1);
}

/**
* @brief  write page
* @param  wr_addr: EEPROM memory address
*         wr_buff: Data buffer to restore write data.
*         wr_len: The length of data to write to EEPROM.
* @retval 0: successful
*         1：failed
*         2：EEPROM type err
*/
uint8 IIC_WR_P(uint32 wr_addr, uint8 *wr_buff, uint32 wr_len)
{
    return 0;
}


/**
* @brief  configure I/O ports
* @param  None
* @retval None
*/
void IIC_GPIO_Init(void)
{
    PRCtrl0 |= BIT6;            //enable IIC
    P9IE    |= 0x02;            //SDA port input enable
}

/**
* @brief  configure timer divider threshold.
* @param  val: IIC timer divider threshold
* @retval None
*/
void IIC_Set_Period(uint16 val)
{
    SITHH = (uint8)(val>>8);       //set high 8 bits of IIC timer divider
    SITHL = (uint8)val;	        //set low 8 bits of IIC timer divider
}

/**
* @brief  transmit start bit
* @param  None
* @retval 0: successful
*         1: failed
*/
uint8 IIC_Start(void)
{
  if (IIC_Wait_Busy())    
        return 1;
    SICFG = IIC_ENDIAN|IIC_TXS; //set IIC endian, enable transmitting start bit.
    SIDAT = 0xFF;               //write any value to transmit start bit.
    
    return 0;
}

/**
* @brief  transmit restart bit
* @param  None
* @retval 0: successful
*         1: failed
*/
uint8 IIC_ReStart(void)
{
     if (IIC_Wait_Busy()) 
        return 1;
    SICFG = IIC_ENDIAN|IIC_TXRS;/*set IIC endian, enable transmitting restart 
                                bit*/
    SIDAT = 0xFF;               //write any value to transmit restart bit.
    
    return 0;
}

/**
* @brief  transmit stop bit
* @param  None
* @retval 0: successful
*         1: failed
*/
uint8 IIC_Stop(void)
{
  if (IIC_Wait_Busy()) 
        return 1;
    SICFG = IIC_ENDIAN|IIC_TXP; //set IIC endian, enable transmitting stop bit.
    SIDAT = 0xFF;				//write any value to transmit stop bit.
    
    return 0;
}

/**
* @brief  check busy state
* @param  None
* @retval 0: successful
*         1: failed(busy)
*/
uint8 IIC_Wait_Busy(void)
{
    
    volatile uint16 i;
    
    CLRWDT();
    /*
    i = 0;
    while (SIFLG & IIC_BUSY)        //check BUSY bit
    {
        i++;
        if (i > 0x3300)             //timeout
            return 1;
    }
    */
    while( BIT1 == (SIFLG & BIT1));
    return 0;
}

/**
* @brief  check ACK
* @param  None
* @retval 0: with ACK
*         1: without ACK
*/
uint8 IIC_Wait_Ack(void)
{
    
    volatile uint16 i;
    
    /*
    
    i = 0;
    while (SIFLG & IIC_ACK)      //check ACK
    {
        i++;
        if (i > 0xB00)
        {
            return 1;
        }
    }
    */
    
    while( BIT1 == (SIFLG & BIT1));
    
    
    return 0;
}

/**
* @brief  transmit 8-bit data byte.
* @param  txd: data to transmit
* @retval 0: successful
*         1: failed
*/
uint8 AIIC_TXD;
uint8 IIC_Send_Data(uint8 txd)
{   	                     
    AIIC_TXD = txd;
    if (IIC_Wait_Busy())
        return 1;
    SIFLG |= IIC_ACK;           //prepare to receive ACK bit
    SICFG = IIC_ENDIAN|IIC_TXD; //set IIC endian, enable transmitting data bits.
    SIDAT = txd;				//transmit data
    if (IIC_Wait_Busy())    
        return 1;
   
    return IIC_Wait_Ack(); 
}

/**
* @brief  receive 8-bit data byte.
* @param  ack: ACK bit
*         rd_val: read data buff pointer
* @retval 0: successful
*         1: failed
*/

uint8 IIC_Read_Data(uint8 *rd_val, uint8 ack)
{
    if (IIC_Wait_Busy())                
        return 1;
    SIFLG = ack;                //set ACK bit
    SICFG = IIC_ENDIAN|IIC_TXD;	//set IIC endian, enable receiving data bits.
    SIDAT = 0xFF;				//fill each data bit with 1
    if (IIC_Wait_Busy())        
        return 1;
    *rd_val = SIDAT;			//read data bits
    return 0;
}

void DelayX(void)
{
    uint8 DelayCount = 38;           //这里延时30就会错误,31就可以正确。目前延时38，保证正确性
    uint8 i;
    while (DelayCount--){ 
        CLRWDT();
        for(i=0;i<30;i++){
            _nop();
        }
    }
}

uint8 IIC_Start_Ex(void)
{
    if (IIC_Wait_Busy())    
        return 1;
    SICFG = IIC_ENDIAN|IIC_TXS; //set IIC endian, enable transmitting start bit.
    SIDAT = 0xFF;               //write any value to transmit start bit.
    
    return 0;
}

uint8 IIC_ReStart_Ex(void)
{
    if (IIC_Wait_Busy()) 
        return 1;
    SICFG = IIC_ENDIAN|IIC_TXRS;/*set IIC endian, enable transmitting restart 
                                bit*/
    SIDAT = 0xFF;               //write any value to transmit restart bit.
    
    return 0;
}


uint8 IIC_Stop_Ex(void)
{
    if (IIC_Wait_Busy()) 
        return 1;
    SICFG = IIC_ENDIAN|IIC_TXP; //set IIC endian, enable transmitting stop bit.
    SIDAT = 0xFF;				//write any value to transmit stop bit.
    
    return 0;
}
uint8 IIC_Send_Data_Ex(uint8 txd)
{
    if (IIC_Wait_Busy())
        return 1;
    SIFLG |= IIC_ACK;           //prepare to receive ACK bit
    SICFG = IIC_ENDIAN|IIC_TXD; //set IIC endian, enable transmitting data bits.
    SIDAT = txd;				//transmit data
    if (IIC_Wait_Busy())    
        return 1;
   
    return IIC_Wait_Ack(); 
}


uint8 IIC_Read_Data_Ex(uint8 *rd_val, uint8 ack)
{
    if (IIC_Wait_Busy())                
        return 1;
    SIFLG = ack;                //set ACK bit
    SICFG = IIC_ENDIAN|IIC_TXD;	//set IIC endian, enable receiving data bits.
    SIDAT = 0xFF;				//fill each data bit with 1
    if (IIC_Wait_Busy())        
        return 1;
    *rd_val = SIDAT;			//read data bits
    return 0;
}

//uint8 IIC_WR_P_Ex(uint16 wr_addr, uint8 *wr_buff, uint16 wr_len)
//{
//    uint8 i;
//    //uint16 tmp1,tmp2;
//    uint16 sub_len;
//    
//    //tmp1 = tmp2 = ~((uint16)EE_PAGE - 1);        
//    //tmp1 &= wr_addr;                        //start page address
//    //tmp2 &= (wr_addr + wr_len - 1);         //end page address
//    
//    //if (tmp1 != tmp2)                       //more than one page
//    //{
//        /*length of data write to the first page*/
//    //    sub_len = EE_PAGE - (wr_addr & (EE_PAGE - 1));
//    //}
//    //else
//    //{
//        sub_len = wr_len;
//    //}
//    
//    //while (1)
//    //{
//        IIC_Start_Ex();
//        
//        
//        #if (EE_TYPE == AT24C512)
//        IIC_Send_Data_Ex(EE_ID);	        //write EEPROM ID
//            
//        IIC_Send_Data_Ex(wr_addr >> 8);    //write high 8 bits of write address
//        
//        #else
//            return 2;
//        #endif
//        
//        IIC_Send_Data_Ex((uint8)wr_addr);     //write low 8 bits of write address
//        
//
//        
//        for (i = 0; i < sub_len; i++)
//        {
//            IIC_Send_Data_Ex(*wr_buff);    //trainsmit one byte data
//            
//            
//            wr_buff++;
//        }
//        IIC_Stop_Ex();                     //transmits stop bit
//        
//        
//        //DelayMs();                //delay for EE_WR_DLY ms
//        
//        //if (sub_len >= wr_len)
//        //    break;
//        
//        //wr_addr += sub_len;
//        //wr_len -= sub_len;
//        //if (wr_len > EE_PAGE)
//        //    sub_len = EE_PAGE;
//        //else
//        //    sub_len = wr_len;
//        //return 0;
//    //}
//    
//    return 0;
//}

//uint8 IIC_RD_P_Ex(uint16 rd_addr, uint8 *rd_buff, uint16 rd_len)
//{
//    uint16 i;
//
//    IIC_Start_Ex();                        //transmit start bit
//    //    return 1;
//    
//    #if (EE_TYPE == AT24C512)
//    IIC_Send_Data_Ex(EE_ID);	            //write EEPROM ID
//    
//    IIC_Send_Data_Ex(rd_addr >> 8);        //write high 8 bits of read address
//    
//    #else
//        return 2;                         
//    #endif
//        
//    IIC_Send_Data_Ex((uint8)rd_addr);         //write low 8 bits of read address
//   
//    IIC_ReStart_Ex();                      //transmit restart
//        
//    
//    IIC_Send_Data_Ex(EE_ID + 1);           //enter receive mode
//    
//
//    for (i = 0; i < rd_len; i++)
//    {
//        if (i == (rd_len - 1))              //receive last byte
//        {
//            IIC_Read_Data_Ex(rd_buff, IIC_NACK);
//                
//        }
//        else
//        {
//            IIC_Read_Data_Ex(rd_buff, IIC_WACK);
//                
//        }
//        rd_buff++;
//    }
//        
//    IIC_Stop_Ex();                         //transmit stop bit
//        
//    
//    return 0;
//}





